package coupon

import (
	"context"
	"strconv"
	"strings"

	"mall/common/globalkey"
	"mall/common/jwt"
	"mall/common/utils/pointy"
	enum "mall/service/backend/common/enum/promotion"
	"mall/service/forum/api/internal/logic/promotion/util"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/forum/api/internal/utils/parse"
	"mall/service/promotion/rpc/promotionclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetCouponTemplateListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetCouponTemplateListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCouponTemplateListLogic {
	return &GetCouponTemplateListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetCouponTemplateListLogic) GetCouponTemplateList(
	req *types.GetCouponTemplateListReq,
	headers *[]*types.Header,
) (resp *types.GetCouponTemplateListResp, err error) {
	userId := jwt.GetUserId(l.ctx)

	page, pageSize := parse.ParsePageInfo(
		req.Current,
		req.PageSize,
		l.svcCtx.Config.Query.DefaultAmount,
		l.svcCtx.Config.Query.MaxAmount,
	)

	// Todo: 删除无用字段
	preload := "couponTemplate:Id,Name,Desc,Members,Type,Mutex,Scope,Mode,Threshhold,DiscountMode,DiscountValue," +
		"GemPrice,PerLimit,ExpireMode,ExpireValue,StartedAt,EndedAt"
	preload += ";promotionMeta:mediaUrl"
	preload += ";promotionMedia:Uid,Uri,Url,Thumbnail,Order,altText"
	eagerLoad := "couponTemplate:couponTotal,promotionMeta,promotionMedia"

	var filters []string
	filters = append(filters, "Status,equalTo:"+strconv.FormatInt(int64(globalkey.StatusStarted), 10))
	filters = append(filters, "Type,in:"+strconv.FormatInt(int64(enum.PromotionCouponTypeReceive), 10)+","+strconv.FormatInt(int64(enum.PromotionCouponTypeExchange), 10))
	if req.ScopeType != nil {
		filters = append(filters, "Scope,equalTo:"+strconv.FormatInt(int64(*req.ScopeType), 10))
	}

	res, err := l.svcCtx.PromotionRpc.GetCouponTemlateList(l.ctx, &promotionclient.BaseListReq{
		Offset:     uint32((page - 1) * pageSize),
		Limit:      uint32(pageSize),
		Preload:    pointy.GetPointer(preload),
		EagerLoad:  pointy.GetPointer(eagerLoad),
		Filter:     pointy.GetPointer(strings.Join(filters, ";")),
		Sorter:     req.Sorter,
		Search:     req.Search,
		VisitorId:  pointy.GetPointer(userId),
		PlatformId: pointy.GetPointer(globalkey.ThirdPartyPlatformWechatMini),
	})
	if err != nil {
		logx.Errorw("GetCouponTemplateList err", logx.Field("detail", err.Error()))
		return nil, err
	}

	var hasNextPage bool
	var hasPreviousPage bool
	if res.HasNextPage != nil && *res.HasNextPage > 0 {
		hasNextPage = true
	}
	if res.HasPreviousPage != nil && *res.HasPreviousPage > 0 {
		hasPreviousPage = true
	}

	resp = &types.GetCouponTemplateListResp{
		BaseListInfo: types.BaseListInfo{
			Current:         page,
			PageSize:        pageSize,
			HasNextPage:     hasNextPage,
			HasPreviousPage: hasPreviousPage,
		},
	}

	for _, v := range res.List {
		var timeRange []string
		if v.StartedAt != nil && v.EndedAt != nil {
			timeRange = []string{*v.StartedAt, *v.EndedAt}
		}

		couponTypeText := util.GetCouponTypeText(v.CouponType)
		mutexTypeText := util.GetMutexTypeText(v.MutexType)
		scopeTypeText := util.GetScopeTypeText(v.ScopeType)
		modeText := util.GetCouponModeText(v.Condition)
		var threshold *string
		if v.ConditionValue != nil {
			if tips := strings.Split(modeText, ","); len(tips) > 0 && len(tips[0]) > 0 {
				threshold = pointy.GetPointer(strings.Replace(tips[0], "N", *v.ConditionValue, 1))
			}
		}
		// discountValue, err := util.GetDiscountValueText(v.DiscountMode, v.DiscountValue)
		var discount *string
		if v.DiscountMode != nil && v.DiscountValue != nil {
			discount = pointy.GetPointer(util.GetDiscountValue(v.DiscountMode, v.DiscountValue))
		}
		expireModeText := util.GetExpireModeText(v.ExpireMode)
		var expire string
		if v.ExpireMode != nil && v.ExpireValue != nil && *v.ExpireMode == uint32(enum.PromotionCouponExpireDynamic) {
			expire = "有效期: 自领取后" + strconv.FormatInt(int64(*v.ExpireValue), 10) + "天"
		}
		if v.ExpireMode != nil && len(timeRange) > 0 && *v.ExpireMode == uint32(enum.PromotionCouponExpireStatic) {
			expire = "有效期:" + strings.Join(timeRange, " - ")
		}
		statusText := util.GetCouponStatusText(v.Status)

		var canReceive bool
		if v.PerLimit == nil || *v.PerLimit == 0 {
			canReceive = true
		} else if v.PerLimit != nil && v.CouponTotal != nil && *v.PerLimit > *v.CouponTotal {
			canReceive = true
		}

		var mediaUrl *string
		if len(v.Meta) > 0 {
			for _, m := range v.Meta {
				if m.Key == nil || m.Value == nil {
					continue
				}

				switch *m.Key {
				case "mediaUrl":
					mediaUrl = m.Value
				}
			}
		}

		var media []*types.TmpMediaInfo
		if len(v.Media) > 0 {
			for _, m := range v.Media {
				var url string
				if m.Url != nil && len(*m.Url) > 0 {
					url = *m.Url
				}
				if len(url) == 0 && m.Uri != nil && len(*m.Uri) > 0 {
					url = *m.Uri
				}

				media = append(media, &types.TmpMediaInfo{
					Uid:       m.Uid,
					Thumbnail: m.Thumbnail,
					Order:     m.Order,
					Url:       pointy.GetPointer(url),
					AltText:   m.AltText,
				})
			}
		} else if mediaUrl != nil {
			media = append(media, &types.TmpMediaInfo{
				Thumbnail: pointy.GetPointer(uint32(1)),
				Order:     pointy.GetPointer(uint32(0)),
				Url:       mediaUrl,
			})
		}

		resp.List = append(resp.List, &types.CouponTemplateInfo{
			Id:                v.Id,
			Name:              v.Name,
			Description:       v.Desc,
			MemberRestriction: v.MemberRestriction,
			CouponType:        v.CouponType,
			CouponTypeText:    pointy.GetPointer(couponTypeText),
			MutexType:         v.MutexType,
			MutexTypeText:     pointy.GetPointer(mutexTypeText),
			ScopeType:         v.ScopeType,
			ScopeTypeText:     pointy.GetPointer(scopeTypeText),
			Mode:              v.Condition,
			ModeText:          pointy.GetPointer(modeText),
			Threshold:         threshold,
			DiscountMode:      v.DiscountMode,
			Discount:          discount,
			PerLimit:          v.PerLimit,
			TimeRange:         timeRange,
			ExpireMode:        v.ExpireMode,
			ExpireModeText:    pointy.GetPointer(expireModeText),
			ExpireValue:       v.ExpireValue,
			Expire:            pointy.GetPointer(expire),
			Status:            v.Status,
			StatusText:        pointy.GetPointer(statusText),
			GemPrice:          v.GemPrice,
			Count:             v.Count,
			CouponTotal:       v.CouponTotal,
			CanReceive:        canReceive,
			Media:             media,
		})
	}

	resp.Total = res.Total

	return resp, nil
}
